import React, {FC, useCallback, useEffect, useMemo, useRef, useState} from "react";
import {Button, Input, Select} from "antd";
import {closeModal, updataModalFooter} from "../../../services/ModalService.tsx";
import {useTranslation} from "react-i18next";
import useStateRef from "../../../customUse/useStateRef.tsx";
import {AxiosGet, AxiosPost} from "../../../services/HttpService.tsx";
import CTable from "../../../global/table/CTable.tsx";
import {getUserInfo} from "../../../services/SecurityService.tsx";
import {coreDispatch} from "../../../utils/StoreUtil.tsx";
import SelectModal from "../select/SelectModal.tsx";
import dayjs from "dayjs";
import Config from "../../../Config.tsx";
import GlobalIcon from "../../../global/GlobalIcon.tsx";
import {getLovs} from "../../../services/ViewService.tsx";
import {showMessage} from "../../../reducer/MsgReducer.tsx";

const defaultItem = {
    "opt": "",
    "itemName": "",
    "drawingNumber": "",
    "weightUnit": "",
    "unitWeight": "",
    "materialGroup": "",
    "materialName": "",
    "materialType": "",
    "companyRoute": "",
    "materialGrade": "",
    "tagsId": "",
    "tagsCn": "",
    "tagsEn": "",
    "tagsPt": "",
    "requesterId": "",
    "requesterName": "",
    "requesterDepartmentId": "",
    "requesterDepartment": "",
    "applicationDate": ""
}

interface EditMaintenanceProps {
    modalKey: string,
    viewName: string,
    flowData: any
}

const EditMaintenance: FC<EditMaintenanceProps> = (props) => {
    const {t} = useTranslation();

    const tableRef = useRef(),
        initDataRef = useRef(),
        materialTypeRef = useRef([]),
        materialGroupRef = useRef([]),
        unitRef = useRef([]),
        dataRef = useRef();

    const [loading, setLoading] = useState(true),
        [data, setData] = useStateRef([], dataRef);

    const formatItem = useCallback((type, n = {}) => {
        const [parentData] = props.flowData;
        let item = {};
        switch (type) {
            case "add":
                item = {
                    "tagsId": "2002qLglWLpic62LiSOkwuQA",
                    "tagsCn": "新增",
                    "tagsEn": "Create",
                    "tagsPt": "Create",
                    companyRoute: "w",
                }
                break;
            case "reference":
                item = {
                    "tagsId": "2002zcsr6KGA1cYLvrtwlgBC",
                    "tagsCn": "引用TC",
                    "tagsEn": "Reference",
                    "tagsPt": "Reference",
                }
                break;
        }
        const userInfo = getUserInfo(), {id, username, groupname} = userInfo;
        return {
            ...defaultItem,
            ...n,
            ...item,
            virtualId: Math.floor(Math.random() * 1000000000) + "",
            parentId: parentData.id,
            requesterId: id,
            requesterName: username,
            requesterDepartmentId: "",
            requesterDepartment: groupname,
            applicationDate: dayjs().format(Config.dateFormat.date),
            isParent: false,
            isChild: true
        }
    }, [props.flowData]);

    const loadLov = useCallback(async () => {
        materialTypeRef.current = (await getLovs("XLOV_Repair_MaterialType")) || [];
        materialGroupRef.current = (await getLovs("XLOV_Repair_MaterialGroup")) || [];
        unitRef.current = (await getLovs("XLOV_Repair_Unit")) || [];
    }, []);

    const loadData = useCallback(async () => {
        const [parentData] = props.flowData;
        setLoading(true)
        const {data} = await AxiosGet("/sf-drs/doc/repairUnit/childBom", {
            id: parentData.id,
            materialCode: parentData.materialCode,
        });
        await loadLov()
        initDataRef.current = data.map(i => ({
            ...i,
            virtualId: Math.floor(Math.random() * 1000000000) + "",
        }));
        setLoading(false)
        setData(initDataRef.current)
    }, [props.flowData])

    useEffect(() => {
        loadData()
    }, [props.flowData]);

    const onAdd = useCallback(() => {
        if (tableRef.current) {
            const node = formatItem("add");
            tableRef.current.addTableData(node, true)
        }
    }, []);

    const onAddReference = useCallback(async () => {
        coreDispatch("modalReducer/createModal", {
            key: `add-TC-material`,
            modalProps: {
                title: t("addTCMaterial"),
                width: 800
            },
            component: SelectModal,
            comProps: {
                search: "form_wandering_maintenance_search",
                isLazyData: true,
                isInitSearch: false,
                rowSelection: "multiple",
                tableApi: {
                    url: "/sf-drs/doc/repairUnit/selectTcSFPurPartList"
                },
                viewName: "col_add_maintenance_list"
            },
            onFinish: async (res: any) => {
                if (res && res.data && tableRef.current) {
                    res.data.forEach((item) => {
                        if (dataRef.current.findIndex(i => i.materialCode === item.materialCode) === -1) {
                            const node = formatItem("reference", item);
                            tableRef.current.addTableData(node, true)
                        }
                    })
                }
            }
        });
    }, []);

    const contrastResult = useCallback((newData, oldData, fieldsToCompare = []) => {
        const cleanNewData = newData.filter(item => item.tagsId !== '');
        const cleanOldData = oldData.filter(item => item.tagsId !== '');
        const oldDataMap = new Map(cleanOldData.map(item => [item.id, item]));
        const result = {
            add: [],
            update: [],
            delete: []
        };
        for (const newItem of cleanNewData) {
            if (!newItem.id) {
                result.add.push(newItem);
                continue;
            }
            const oldItem = oldDataMap.get(newItem.id);
            if (oldItem) {
                const isUpdated = fieldsToCompare.some(field => newItem[field] !== oldItem[field]);
                if (isUpdated) {
                    result.update.push(newItem);
                }
            }
        }
        const newDataIds = new Set(cleanNewData.map(item => item.id));
        for (const oldItem of cleanOldData) {
            if (!newDataIds.has(oldItem.id)) {
                result.delete.push(oldItem.id);
            }
        }
        return result;
    }, []);

    const onOk = useCallback(async () => {
        const allData = tableRef.current.gridTable().getRenderedNodes();
        let newData = [];
        allData.forEach(({data}) => {
            if (!data.isParent) {
                newData.push(data)
            }
        })
        const requireAttrs = ["itemName", "drawingNumber", "unitWeight", "weightUnit", "materialName", "materialGrade"];
        for (const item of newData) {
            if (item.tagsId !== "2002qLglWLpic62LiSOkwuQA") {
                continue;
            }
            for (const attrName of requireAttrs) {
                if (!item[attrName].trim()) {
                    showMessage({
                        type: "error",
                        msg: t(attrName) + " " + t("notNullValue")
                    })
                    return;
                }
            }
        }
        let params = contrastResult(newData, initDataRef.current, [...requireAttrs, "materialGroup", "materialType", "companyRoute"]);
        const [parentData] = props.flowData;
        const result = await AxiosPost("/sf-drs/doc/repairUnit/editPurPartBom", {
            ...params,
            parentId: parentData.id,
            materialCode: parentData.materialCode,
        });
        result.code == "1" && await closeModal(props.modalKey, async () => {
            return result;
        });
    }, [props.flowData]);

    useEffect(() => {
        const btns = [
            <Button color="cyan" variant="solid" onClick={onAdd}>{t("add")}</Button>,
            <Button color="cyan" variant="solid" onClick={onAddReference}>{t("addTCMaterial")}</Button>,
            <Button type="primary" onClick={onOk}>{t("determine")}</Button>,
            <Button key="cancel"
                    onClick={() => {
                        closeModal(props.modalKey, false)
                    }}>{t("cancel")}</Button>]
        updataModalFooter(props.modalKey, btns)
    }, []);

    const textEdit = useCallback(({value, node, colDef}) => {
        const {data} = node;
        if (data.isParent || data.tagsId !== '2002qLglWLpic62LiSOkwuQA') {
            return <span>{value}</span>
        }
        const field = colDef.field;
        return (<div>
            <Input size="small" defaultValue={value} onChange={(e) => {
                node.updateData({...node.data, [field]: e.target.value})
            }}/>
        </div>)
    }, []);

    const getSelectOption = useCallback((field) => {
        switch (field) {
            case "weightUnit":
                return unitRef.current;
            case "materialGroup":
                return materialGroupRef.current;
            case "materialType":
                return materialTypeRef.current;
        }
    })

    const selectEdit = useCallback(({value, node, colDef}) => {
        const {data} = node;
        if (data.isParent || data.tagsId !== '2002qLglWLpic62LiSOkwuQA') {
            return <span>{value}</span>
        }
        const field = colDef.field;
        const options = getSelectOption(field);
        if (!options) {
            return <span>{value}</span>
        }
        return (<div>
            <Select
                size="small"
                defaultValue={value}
                style={{width: "100%"}}
                fieldNames={{label: "text", value: "id"}}
                onChange={(value) => {
                    node.updateData({...node.data, [field]: value})
                }}
                options={options}
            />
        </div>)
    }, []);

    const onSelectMaterials = useCallback((node) => {
        coreDispatch("modalReducer/createModal", {
            key: `maintain-materials`,
            modalProps: {
                title: t("maintainMaterials"),
                width: 800
            },
            component: SelectModal,
            comProps: {
                search: "form_maintain_materials_search",
                isLazyData: true,
                rowSelection: "single",
                rowKey: "materialGrade",
                tableApi: {
                    url: "/sf-drs/doc/repairUnit/getMatPart"
                },
                viewName: "col_maintain_materials_list"
            },
            onFinish: async (res: any) => {
                if (res && res.data) {
                    const [materials] = res.data;
                    node.updateData({
                        ...node.data,
                        materialGrade: materials.materialGrade,
                        materialName: materials.materialName
                    });
                }
            }
        });
    }, [])

    const optEdit = useCallback(({value, node}) => {
        const {data} = node;
        if (data.isParent || !data.tagsId) {
            return <span>{value}</span>
        }
        return (<div style={{textAlign: "right"}}>
            {data.tagsId === "2002qLglWLpic62LiSOkwuQA" ? <Button size="small" type="primary" onClick={() => {
                onSelectMaterials(node)
            }} style={{marginRight: 10}}>{t("maintainMaterials")}</Button> : null}
            <Button size="small" color="danger" variant="solid" icon={<GlobalIcon name="icon-delete"/>} onClick={() => {
                if (tableRef.current) {
                    tableRef.current.deleteTableData([data.virtualId])
                }
            }}/>
        </div>)
    }, []);

    const otherRenderFn = useCallback(() => {
        return {
            textEdit: textEdit,
            selectEdit: selectEdit,
            optEdit: optEdit
        }
    }, []);

    const getDataSource = useCallback((parentData, data) => {
        return [{
            ...parentData,
            virtualId: parentData.id,
            children: data
        }]
    }, [])

    const renderEditMaintenance = useMemo(() => {
        if (loading) {
            return null;
        }
        const {viewName, flowData = []} = props,
            [parentData] = flowData;
        const dataSource = getDataSource(parentData, data)
        return (
            <div className="sf_core_edit_maintenance" style={{height: '70vh'}}>
                <CTable
                    init={tableRef}
                    view={viewName}
                    isShowHeader={false}
                    rowKey="virtualId"
                    isTreeTable={true}
                    dataSource={dataSource}
                    otherRenderFn={otherRenderFn()}
                    autoExpand={true}
                    tableApi={{}}
                />
            </div>
        )
    }, [props, data, loading]);

    return (renderEditMaintenance);
};

export default React.memo(EditMaintenance);